home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-04 | 82.0 KB | 3,756 lines |
- *** ScR ***
-
- *** NOTES ***
-
- * The sampler routines are just for fun. Since interrupts must not be disabled,
- * there are lots of clicks.
-
- ;------------
-
- VERSION EQU 4
- REVISION EQU 13
- DATE MACRO
- dc.b "3.8.97"
- ENDM
- VERS MACRO
- dc.b "paula.audio 4.13"
- ENDM
- VSTRING MACRO
- VERS
- dc.b " ("
- DATE
- dc.b ")",13,10,0
- ENDM
- VERSTAG MACRO
- dc.b 0,"$VER: "
- VERS
- dc.b " ("
- DATE
- dc.b ")",0
- ENDM
-
- incdir include:
-
- include hardware/all.i
-
- include devices/audio.i
- include dos/dos.i
- include exec/exec.i
- include graphics/gfxbase.i
- include intuition/intuitionbase.i
- include intuition/screens.i
- include resources/misc.i
- include resources/card.i
- include utility/utility.i
- include utility/hooks.i
-
- include lvo/cardres_lib.i
- include lvo/dos_lib.i
- include lvo/exec_lib.i
- include lvo/graphics_lib.i
- include lvo/intuition_lib.i
- include lvo/utility_lib.i
-
- include devices/ahi.i
- include libraries/ahi_sub.i
- include lvo/ahi_sub_lib.i
-
- include macros.i
-
- DEBUG_DETAIL SET 0
-
- _ciaa EQU $bfe001
- _ciab EQU $bfd000
-
- PALFREQ EQU 3546895
- NTSCFREQ EQU 3579545
- MINPER EQU 62
-
- RECORDSAMPLES EQU 1024
-
-
- * paula.audio extra tags
- AHIDB_Paula14Bit EQU AHIDB_UserBase+0 * Boolean
- AHIDB_PaulaTable EQU AHIDB_UserBase+1 * Boolean
-
- * paulaBase (private)
- STRUCTURE paulaBase,LIB_SIZE
- UBYTE pb_Flags
- UBYTE pb_Pad1
- UWORD pb_Pad2
- APTR pb_SysLib
- ULONG pb_SegList
- APTR pb_GfxLib
- APTR pb_UtilLib
- APTR pb_DosLib
- APTR pb_IntuiLib
- APTR pb_MiscResource
- APTR pb_CardResource
- LABEL paulaBase_SIZEOF
-
- * paula (private) ahiac_DriverData points to this structure.
- STRUCTURE paula,0
- UBYTE p_Flags
- UBYTE p_Parallel ;TRUE if parport allocated
- UWORD p_DisableCount ;AHIsub_Enable/AHIsub_Disable cnt
-
- ULONG p_MinBufferLength
- APTR p_DMAbuffer ;Chipmem play buffer
- APTR p_CalibrationTable
-
- ULONG p_DoubleBufferOffset
-
- UWORD p_SwapChannels
- UWORD p_Pad1
-
- ; Pointers to chipmem play buffer
-
- LABEL p_AudPtrs
- APTR p_AudPtr1A
- APTR p_AudPtr2A
- APTR p_AudPtr3A
- APTR p_AudPtr4A
- APTR p_AudPtr1B
- APTR p_AudPtr2B
- APTR p_AudPtr3B
- APTR p_AudPtr4B
-
- UWORD p_AudPer
- UWORD p_OutputVolume
- UWORD p_MonitorVolume
- UWORD p_Input
-
- APTR p_AudioCtrl
-
- APTR p_audioport
- APTR p_audioreq
- ULONG p_audiodev
- APTR p_ParBitsUser
- APTR p_ParPortUser
- APTR p_SerBitsUser
- APTR p_CardHandle
-
- STRUCT p_PlayInt,IS_SIZE
- STRUCT p_PlaySoftInt,IS_SIZE
- STRUCT p_RecInt,IS_SIZE
- STRUCT p_RecSoftInt,IS_SIZE
-
- ULONG p_LoopTimes
-
- LABEL p_PlayerHookRegs
- APTR p_PlayerHook
- ULONG p_Reserved
- FPTR p_PlayerEntry ;p_PlayerHook->h_Entry
-
- LABEL p_MixHookRegs
- APTR p_MixHook
- APTR p_Mixbuffer
- FPTR p_MixEntry ;p_MixHook->h_Entry
-
- LABEL p_RecIntDataAura
- APTR p_AuraAddress
-
- LABEL p_RecIntData
- APTR p_RecFillPtr
- UWORD p_RecFillCount
- UWORD p_Pad2
- APTR p_RecBuffer1
- APTR p_RecBuffer2
- APTR p_RecSoftIntPtr
-
- LABEL p_RecordMessage
- ULONG p_rmType
- APTR p_rmBuffer
- ULONG p_rmLength
-
- STRUCT p_CalibrationArray,256
- LABEL paula_SIZEOF
-
- * p_Flags
- BITDEF P,14BIT,0
- BITDEF P,HIFI,1
- PB_STEREO EQU AHIACB_STEREO ;=2
- PF_STEREO EQU AHIACF_STEREO
-
- Start:
- moveq #-1,d0
- rts
-
- RomTag:
- DC.W RTC_MATCHWORD
- DC.L RomTag
- DC.L EndCode
- DC.B RTF_AUTOINIT
- DC.B VERSION ;version
- DC.B NT_LIBRARY
- DC.B 0 ;pri
- DC.L LibName
- DC.L IDString
- DC.L InitTable
-
- LibName: dc.b "paula.audio",0
- IDString: VSTRING
- gfxName: GRAPHICSNAME
- utilName: UTILITYNAME
- dosName: DOSNAME
- intuiName: dc.b "intuition.library",0
- miscName: MISCNAME
- cardName: dc.b "card.resource",0
- filterVar: dc.b "AHIpaulaFilterFreq",0
- screenVar: dc.b "AHIpaulaSampleLimit",0
- bufferVar: dc.b "AHIpaulaBufferLength",0
- swapVar: dc.b "AHIpaulaSwapChannels",0
- cnop 0,2
-
- InitTable:
- DC.L paulaBase_SIZEOF
- DC.L funcTable
- DC.L dataTable
- DC.L initRoutine
-
- funcTable:
- dc.l Open
- dc.l Close
- dc.l Expunge
- dc.l Null
- *
- dc.l AHIsub_AllocAudio
- dc.l AHIsub_FreeAudio
- dc.l AHIsub_Disable
- dc.l AHIsub_Enable
- dc.l AHIsub_Start
- dc.l AHIsub_Update
- dc.l AHIsub_Stop
- dc.l AHIsub_SetVol
- dc.l AHIsub_SetFreq
- dc.l AHIsub_SetSound
- dc.l AHIsub_SetEffect
- dc.l AHIsub_LoadSound
- dc.l AHIsub_UnloadSound
- dc.l AHIsub_GetAttr
- dc.l AHIsub_HardwareControl
- dc.l -1
-
- dataTable:
- INITBYTE LN_TYPE,NT_LIBRARY
- INITLONG LN_NAME,LibName
- INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
- INITWORD LIB_VERSION,VERSION
- INITWORD LIB_REVISION,REVISION
- INITLONG LIB_IDSTRING,IDString
- DC.L 0
-
- initRoutine:
- movem.l d1/a0/a1/a5/a6,-(sp)
- move.l d0,a5
- move.l a6,pb_SysLib(a5)
- move.l a0,pb_SegList(a5)
- lea gfxName(pc),a1
- moveq #0,d0
- call OpenLibrary
- move.l d0,pb_GfxLib(a5)
- bne.b .gfxOK
- ALERT AG_OpenLib|AO_GraphicsLib
- moveq #0,d0
- bra .exit
- .gfxOK
- lea utilName(pc),a1
- moveq #0,d0
- call OpenLibrary
- move.l d0,pb_UtilLib(a5)
- bne.b .utilOK
- ALERT AG_OpenLib|AO_UtilityLib
- moveq #0,d0
- bra .exit
- .utilOK
- lea dosName(pc),a1
- moveq #0,d0
- call OpenLibrary
- move.l d0,pb_DosLib(a5)
- bne.b .dosOK
- ALERT AG_OpenLib|AO_DOSLib
- moveq #0,d0
- bra .exit
- .dosOK
- lea intuiName(pc),a1
- moveq #0,d0
- call OpenLibrary
- move.l d0,pb_IntuiLib(a5)
- bne.b .intuiOK
- ALERT AG_OpenLib|AO_Intuition
- moveq #0,d0
- bra .exit
- .intuiOK
- lea miscName(pc),a1
- call OpenResource
- move.l d0,pb_MiscResource(a5)
- bne.b .miscOK
- ALERT AG_OpenRes|AO_MiscRsrc
- moveq #0,d0
- bra .exit
- .miscOK
- lea cardName(pc),a1
- call OpenResource
- move.l d0,pb_CardResource(a5) ;Don't fail on error
-
- move.l a5,d0
- .exit
- movem.l (sp)+,d1/a0/a1/a5/a6
- rts
-
- Open:
- moveq #0,d0
- addq.w #1,LIB_OPENCNT(a6)
- bclr.b #LIBB_DELEXP,pb_Flags(a6)
- move.l a6,d0
- .exit
- rts
-
- Close:
- moveq #0,d0
- subq.w #1,LIB_OPENCNT(a6)
- bne.b .exit
- btst.b #LIBB_DELEXP,pb_Flags(a6)
- beq.b .exit
- bsr Expunge
- .exit
- rts
-
- Expunge:
- movem.l d1/d2/a0/a1/a5/a6,-(sp)
- move.l a6,a5
- move.l pb_SysLib(a5),a6
- tst.w LIB_OPENCNT(a5)
- beq.b .notopen
- bset.b #LIBB_DELEXP,pb_Flags(a5)
- moveq #0,d0
- bra.b .Expunge_end
- .notopen
- move.l pb_IntuiLib(a5),a1
- call CloseLibrary
-
- move.l pb_DosLib(a5),a1
- call CloseLibrary
-
- move.l pb_UtilLib(a5),a1
- call CloseLibrary
-
- move.l pb_GfxLib(a5),a1
- call CloseLibrary
-
- move.l pb_SegList(a5),d2
- move.l a5,a1
- call Remove
-
- moveq #0,d0
- move.l a5,a1
- move.w LIB_NEGSIZE(a5),d0
- sub.l d0,a1
- add.w LIB_POSSIZE(a5),d0
- call FreeMem
- move.l d2,d0
- .Expunge_end
- movem.l (sp)+,d1/d2/a0/a1/a5/a6
- rts
-
- Null:
- moveq #0,d0
- rts
-
- * BeginIO(ioRequest)(a1) (From amiga.lib)
- BeginIO:
- move.l a1,a0 ;probably not neccesary
- push a6
- move.l IO_DEVICE(a1),a6
- jsr -30(a6)
- pop a6
- rts
-
- ****** [driver].audio/--background-- ****************************************
- *
- * OVERVIEW
- *
- * DRIVER VERSIONS
- *
- * The lowest supported driver version is 2. If you use any feature
- * introduced in later versions of AHI, you should set the driver
- * version to the same version as the features were introduced with.
- * Example: You use PreTimer() and PostTimer(), and since these
- * calls were added in V4 of ahi.device, your driver's version should
- * be 4, too.
- *
- * AUDIO ID NUMBERS
- *
- * Just some notes about selecting ID numbers for different modes:
- * It is up to the driver programmer to chose which modes should be
- * available to the user. Take care when selecting.
- *
- * The upper word is the hardware ID, and can only be allocated by
- * Martin Blom <lcs@lysator.liu.se>. The lower word is free, but in
- * order to allow enhancements, please only use bit 0 to 3 for modes!
- * If your driver supports multiple sound cards, use bit 12-15 to
- * select card (first one is 0). If your sound card has multiple
- * AD/DA converters, you can use bit 8-11 to select them (the first
- * should be 0).
- *
- * Set the remaining bits to zero.
- *
- * Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
- * currently available. Use AHI:Developer/Support/sift to make sure your
- * mode descriptor file is a legal IFF file.
- *
- * I do reserve the right to change the rules if I find them incorrect!
- *
- *****************************************************************************
- *
- *
-
- ****** [driver].audio/AHIsub_AllocAudio *************************************
- *
- * NAME
- * AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
- *
- * SYNOPSIS
- * result = AHIsub_AllocAudio( tags, audioctrl);
- * D0 A1 A2
- *
- * ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * Allocate and initialize the audio hardware. Decide if and how you
- * wish to use the mixing routines provided by 'ahi.device', by looking
- * in the AHIAudioCtrlDrv structure and parsing the tag list for tags
- * you support.
- *
- * 1) Use mixing routines with timing:
- * You will need to be able to play any number of samples from
- * about 80 up to 65535 with low overhead.
- * · Update AudioCtrl->ahiac_MixFreq to nearest value that your
- * hardware supports.
- * · Return AHISF_MIXING|AHISF_TIMING.
- * 2) Use mixing routines without timing:
- * If the hardware can't play samples with any length, use this
- * alternative and provide timing yourself. The buffer must
- * take less than about 20 ms to play, preferable less than 10!
- * · Update AudioCtrl->ahiac_MixFreq to nearest value that your
- * hardware supports.
- * · Store the number of samples to mix each pass in
- * AudioCtrl->ahiac_BuffSamples.
- * · Return AHISF_MIXING
- * Alternatively, you can use the first method and call the
- * mixing hook several times in a row to fill up a buffer.
- * In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
- * return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
- * If the buffer is so large that it takes more than (approx.) 10 ms to
- * play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
- * should return FALSE.
- * 3) Don't use mixing routines:
- * If your hardware can handle everything without using the CPU to
- * mix the channels, you tell 'ahi.device' this by not setting
- * either the AHISB_MIXING or the AHISB_TIMING bit.
- *
- * If you can handle stereo output from the mixing routines, also set
- * bit AHISB_KNOWSTEREO.
- *
- * If you can handle hifi (32 bit) output from the mixing routines,
- * set bit AHISB_KNOWHIFI.
- *
- * If this driver can be used to record samples, set bit AHISB_CANRECORD,
- * too (regardless if you use the mixing routines in AHI or not).
- *
- * If the sound card has hardware to do DSP effects, you can set the
- * AHISB_CANPOSTPROCESS bit. The output from the mixing routines will
- * then be two separate buffers, one wet and one dry. You should then
- * apply the Fx on the wet buffer, and post-mix the two buffers before
- * you send the samples to the DAC. (V4)
- *
- * INPUTS
- * tags - pointer to a taglist.
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * TAGS
- * The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
- * NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
- *
- * RESULT
- * Flags, defined in <libraries/ahi_sub.h>.
- *
- * EXAMPLE
- *
- * NOTES
- * You don't have to clean up on failure, AHIsub_FreeAudio() will
- * always be called.
- *
- * BUGS
- *
- * SEE ALSO
- * AHIsub_FreeAudio(), AHIsub_Start()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_AllocAudio:
- pushm d2-d7/a2-a6
- move.l a6,a5
-
- move.l a1,d3
-
- * Allocate the 'paula' structure (our variables)
- move.l pb_SysLib(a5),a6
- move.l #paula_SIZEOF,d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,ahiac_DriverData(a2)
- beq .error_nopaula
- move.l d0,a3
-
- * Initialize some fields...
- move.l #-1,p_audiodev(a3)
- move.l #-1,p_ParBitsUser(a3)
- move.l #-1,p_ParPortUser(a3)
- move.l #-1,p_SerBitsUser(a3)
- move.l a2,p_AudioCtrl(a3)
- lea p_RecSoftInt(a3),a0
- move.l a0,p_RecSoftIntPtr(a3)
- move.l #AHIST_S16S,p_rmType(a3)
- move.l #RECORDSAMPLES,p_rmLength(a3)
- move.w #64,p_OutputVolume(a3)
-
- * Translate tags to flags
- moveq #0,d2
- move.l pb_UtilLib(a5),a6
- move.l #AHIDB_Paula14Bit,d0
- moveq #0,d1
- move.l d3,a0 ;tag list
- call GetTagData
- tst.l d0
- beq.b .no14bit
- moveq #PF_14BIT,d2
- .no14bit
- move.l #AHIDB_HiFi,d0
- moveq #0,d1
- move.l d3,a0 ;tag list
- call GetTagData
- tst.l d0
- beq.b .noHiFi
- or.b #PF_HIFI,d2
- .noHiFi
- move.l ahiac_Flags(a2),d0
- and.b #PF_STEREO,d0 ;same as AHIACF_STEREO
- or.b d2,d0
- move.b p_Flags(a3),d1
- and.b #~(PF_STEREO|PF_HIFI|PF_14BIT),d1
- or.b d0,d1
- move.b d1,p_Flags(a3)
-
- * Check if a table should be used (14 bit calibration)
- move.l #AHIDB_PaulaTable,d0
- moveq #0,d1
- move.l d3,a0 ;tag list
- call GetTagData
- tst.l d0
- beq .notable
-
- * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
- * and initialize the table.
- * FIXIT: The calibration file should move to a special chunk in
- * 'DEVS:AudioModes/PAULA'.
- move.l pb_DosLib(a5),a6
- lea .calibname(pc),a0
- move.l a0,d1
- move.l #MODE_OLDFILE,d2
- call Open
- move.l d0,d4
- beq .nocalib
- move.l d0,d1
- lea p_CalibrationArray(a3),a0
- move.l a0,d2
- move.l #256,d3
- call Read
- cmp.l d0,d3
- beq .tableloaded
- .nocalib
- ; Fill defaults
- lea p_CalibrationArray(a3),a0
- move.w #254-1,d0
- .initcalib
- move.b #$55,(a0)+
- dbf d0,.initcalib
- move.b #$7f,(a0)+
- .tableloaded
- move.l d4,d1
- beq.b .nofile
- call Close
- .nofile
- move.l pb_SysLib(a5),a6
- move.l #65536*2,d0
- move.l #MEMF_PUBLIC,d1
- call AllocVec
- move.l d0,p_CalibrationTable(a3)
- beq.b .notable
- move.l d0,a0 ;table
- lea p_CalibrationArray(a3),a1
- bsr.w _CreateTable
- .notable
-
- * Get the minimum chip buffer size
- moveq #0,d5 ;Default
- move.l pb_DosLib(a5),a6
- subq.l #8,sp ;local label
- move.w #("0"<<8)|0,(sp) ;Initialize as "0"
- lea bufferVar(pc),a0
- move.l a0,d1
- move.l sp,d2
- moveq.l #8,d3
- moveq.l #0,d4
- call GetVar
- cmp.l #-1,d0
- beq .gotlength
- move.l sp,d1
- pea.l 0.w
- move.l sp,d2
- call StrToLong
- move.l (sp)+,d5
- .gotlength
- addq.l #8,sp
- ; d5 is now the buffer length
- move.l d5,p_MinBufferLength(a3)
-
- * Check if we should swap left & right channels
- moveq #0,d5 ;Default
- move.l pb_DosLib(a5),a6
- subq.l #8,sp ;local label
- move.w #("0"<<8)|0,(sp) ;Initialize as "0"
- lea swapVar(pc),a0
- move.l a0,d1
- move.l sp,d2
- moveq.l #8,d3
- moveq.l #0,d4
- call GetVar
- cmp.l #-1,d0
- beq .gotswap
- move.l sp,d1
- pea.l 0.w
- move.l sp,d2
- call StrToLong
- move.l (sp)+,d5
- .gotswap
- addq.l #8,sp
- ; d5 is now the buffer length
- move.w d5,p_SwapChannels(a3)
-
- * allocate audio.device
- move.l pb_SysLib(a5),a6
- call CreateMsgPort
- move.l d0,p_audioport(a3)
- beq .error_noport
- moveq #ioa_SIZEOF,d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_audioreq(a3)
- beq .error_noreqmem
- move.l d0,a0
- move.l p_audioport(a3),MN_REPLYPORT(a0)
- clr.w ioa_AllocKey(a0)
- move.b #127,LN_PRI(a0) ;steal it!
- lea .audiochannelarray(pc),a1
- move.l a1,ioa_Data(a0)
- move.l #1,ioa_Length(a0)
- lea .audioname(pc),a0
- moveq #0,d0
- move.l p_audioreq(a3),a1
- moveq #0,d1
- call OpenDevice
- move.l d0,p_audiodev(a3)
- bne .error_noaudiodev ;somebody already owns the hardware (could be us!)
- move.l p_audioreq(a3),a1
- move.w #CMD_RESET,IO_COMMAND(a1)
- bsr.w BeginIO ;clear attach, stop sound.
- move.l p_audioport(a3),a0
- call WaitPort
- move.l p_audioport(a3),a0
- call GetMsg
-
- move.l pb_DosLib(a5),a6
- moveq #1,d1
- call Delay
-
- * test if mode supports recording
- btst #PB_14BIT,p_Flags(a3)
- bne .dontgetsampler ;no record if 14 bit mode
-
- * try to allocate parallel port
- clr.b p_Parallel(a3)
- move.l pb_MiscResource(a5),a6
- moveq #MR_PARALLELBITS,d0
- lea IDString(pc),a1
- jsr MR_ALLOCMISCRESOURCE(a6)
- move.l d0,p_ParBitsUser(a3)
- bne .no_parrallel
- moveq #MR_PARALLELPORT,d0
- lea IDString(pc),a1
- jsr MR_ALLOCMISCRESOURCE(a6)
- move.l d0,p_ParPortUser(a3)
- bne .no_parrallel
-
- move.b #TRUE,p_Parallel(a3)
- move.b #0,_ciaa+ciaddrb ;make PB0-PB7 inputs
- .no_parrallel
-
- * allocate Aura sampler
- clr.l p_AuraAddress(a3)
- move.l pb_CardResource(a5),d0
- beq .no_aura
- move.l d0,a6
- call GetCardMap
- tst.l d0
- beq .no_aura
- move.l d0,a0
- move.l cmm_IOMemory(a0),d2
- beq .no_aura
-
- move.l pb_SysLib(a5),a6
- moveq #CardHandle_SIZEOF,d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_CardHandle(a3)
- beq .no_aura
-
- move.l pb_CardResource(a5),a6
- move.l d0,a1
- move.l #IDString,LN_NAME(a1)
- move.b #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
- call OwnCard
- tst.l d0
- bne .no_aura
-
- move.l p_CardHandle(a3),a1
- call BeginCardAccess
-
- move.l d2,p_AuraAddress(a3)
- .no_aura
- .dontgetsampler
-
-
- * initialize interrupts (Only dummy function pointers at this time)
-
- * p_PlayInt (the main playback interrupt)
- move.b #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
- move.l #LibName,LN_NAME+p_PlayInt(a3)
- move.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
- move.l a3,IS_DATA+p_PlayInt(a3)
-
- * p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
- move.b #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
- move.l #LibName,LN_NAME+p_PlaySoftInt(a3)
- move.l #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
- move.l a3,IS_DATA+p_PlaySoftInt(a3)
-
- * p_RecInt (the interrupt used for recording)
- move.b #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
- move.l #LibName,LN_NAME+p_RecInt(a3)
- move.l #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
- clr.l IS_DATA+p_RecInt(a3)
-
- * p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
- move.b #32,LN_PRI+p_RecSoftInt(a3)
- move.b #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
- move.l #LibName,LN_NAME+p_RecSoftInt(a3)
- move.l #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
- move.l a3,IS_DATA+p_RecSoftInt(a3)
-
- * Make sure no interrupts occur until AHIsub_Start() is called
- move.w #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,custom+INTENA
-
- * Update ahiac_MixFreq to what the mixing/sampling frequency really is
- move.l ahiac_MixFreq(a2),d1
- bsr calcperiod
- move.l d0,ahiac_MixFreq(a2) ;store actual freq
-
- * Check the AHIpaulaFilterFreq variable.
- * If the mixing frequency is higher than this one, set disable the filter,
- * else enable it.
- moveq #0,d5 ;Default freq
- move.l pb_DosLib(a5),a6
- subq.l #8,sp ;local label
- move.w #("0"<<8)|0,(sp) ;Initialize as "0"
- lea filterVar(pc),a0
- move.l a0,d1
- move.l sp,d2
- moveq.l #8,d3
- moveq.l #0,d4
- call GetVar
- cmp.l #-1,d0
- beq .gotfreq
- move.l sp,d1
- pea.l 0.w
- move.l sp,d2
- call StrToLong
- move.l (sp)+,d5
- .gotfreq
- addq.l #8,sp
- ; d5 is now the freq
-
- cmp.l ahiac_MixFreq(a2),d5
- bls .no_filter
- bclr #1,$bfe001 ;turn audio filter on
- bra .filter_set
- .no_filter
- bset #1,$bfe001 ;turn audio filter off
- .filter_set
-
- moveq #AHISF_KNOWSTEREO|AHISF_KNOWHIFI|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
- .exit
- popm d2-d7/a2-a6
- rts
-
- .error_noaudiodev
- .error_noreqmem
- .error_noport
- .error_nopaula
- moveq #AHISF_ERROR,d0
- bra.b .exit
-
- .audiochannelarray
- dc.b 1+2+4+8
- .audioname
- AUDIONAME
- .calibname
- dc.b "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
- even
- .cardhandle:
- dc.l 0,0 ;ln_Succ, ln_Pred
- dc.b 0 ;ln_Type
- dc.b 0 ;ln_Pri
- dc.l IDString ;ln_Name
- dc.l 0,0,0 ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
- dc.b (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
- even
-
- ;in:
- * d1 MixFreq
- * a5 paulaBase
- ;out:
- * d0 New MixFreq
- * d1.w Period
- ;description:
- * Calculate and return the best period and the actual frequency.
- calcperiod:
- pushm d2-d7/a2-a6
- move.l #PALFREQ,d2 ;PAL
- move.l pb_GfxLib(a5),a0
- move.w gb_DisplayFlags(a0),d0
- btst #REALLY_PALn,d0
- bne.b .1
- move.l #NTSCFREQ,d2 ;NTSC
- .1
- move.l d2,d0
- move.l d1,d3
- move.l pb_UtilLib(a5),a1
- jsr _LVOUDivMod32(a1)
- lsl.l #1,d1
- cmp.l d3,d1
- bmi.b .3
- addq.l #1,d0
- .3
- move.w d0,d4
- * d4 is now period. Check if is it a valid one, depending on current display mode
- bsr checkvideo
- moveq #MINPER,d1
- tst.l d0
- bne .5
- moveq #MINPER*2,d1
- .5
- cmp.w d1,d4
- bhs.b .6
- move.w d1,d4
- .6
- moveq #0,d1
- move.w d4,d1
- move.l d2,d0
- move.l d1,d3
- move.l pb_UtilLib(a5),a1
- jsr _LVOUDivMod32(a1)
- lsl.l #1,d1
- cmp.l d3,d1
- bmi.b .4
- addq.l #1,d0
- .4
- move.w d4,d1
- popm d2-d7/a2-a6
- rts
-
- ;in:
- * a5 paulaBase
- ;out:
- * d0 TRUE if current mode is double
- ;description:
- * Checks if the current screen mode is doublescan.
- * This routine is a bit ugly, but it does get the job
- * done, even if a graphic card is used.
- checkvideo:
- pushm d2-d7/a2-a6
-
- * Check the AHIpaulaSampleLimit variable.
- * If 1, allow > 28 kHz frequencies, if 0, don't. If not present,
- * check the screen mode.
- move.l pb_DosLib(a5),a6
- clr.w -(sp) ;Initialize local data
- lea screenVar(pc),a0
- move.l a0,d1
- move.l sp,d2
- moveq.l #2,d3
- moveq.l #0,d4
- call GetVar
- move.w (sp)+,d1
- cmp.l #-1,d0
- beq .testfreq
- cmp.w #"0"<<8|0,d1
- beq .no31k
- cmp.w #"1"<<8|0,d1
- beq .is31k
-
- .testfreq
-
- ; Chip revision test
-
- move.l pb_GfxLib(a5),a0
- move.b gb_ChipRevBits0(a0),d0
- and.b #GFXF_HR_DENISE|GFXF_AA_LISA,d0
- beq .no31k ; OCS: No 31 kHz modes
-
- ; Native screen test
-
- moveq #0,d0
- move.l pb_IntuiLib(a5),a6
- call LockIBase
- move.l d0,d2
- move.l ib_FirstScreen(a6),a0
- lea sc_ViewPort(a0),a0
- move.l pb_GfxLib(a5),a6
- call GetVPModeID
- move.l d2,a0
- move.l d0,d2
- move.l pb_IntuiLib(a5),a6
- call UnlockIBase
-
- ; "Check" if native screen
- move.l d2,d0
- and.l #$40000000,d0
- bne .gfxcard
-
- ; It is!
- sub.w #mtr_SIZEOF,sp ;local storage
- suba.l a0,a0
- move.l sp,a1
- move.l #mtr_SIZEOF,d0
- move.l #DTAG_MNTR,d1
- move.l pb_GfxLib(a5),a6
- call GetDisplayInfoData
-
- moveq #1,d1
- add.w mtr_TotalRows(sp),d1
- sub.w mtr_MinRow(sp),d1
- move.w mtr_TotalColorClocks(sp),d2
- mulu.w mtr_TotalRows(sp),d2
-
- add.w #mtr_SIZEOF,sp ;restore stack
- tst.l d0
- beq .no31k
- ; Calculate TotalColorClocks*TotalRows/(2*(TotalRows-MinRow+1)
- add.l d1,d1
- beq .no31k
- divu d1,d2
- cmp.w #64,d2 ; 64 is an round nice number, no?
- bls .is31k
- bra .no31k
-
- .gfxcard
-
- ; Picasso '96 test
-
- lea .picasso96(pc),a1
- move.l pb_SysLib(a5),a6
- call FindTask
- tst.l d0
- beq .cgfx ; Not P96, assume CyberGraphX
-
- move.l pb_DosLib(a5),a6
- clr.l -(sp) ;Initialize local data
- lea .p96amigavideo(pc),a0
- move.l a0,d1
- move.l sp,d2
- moveq.l #4,d3
- moveq.l #0,d4
- call GetVar
- move.l (sp)+,d1
- swap.w d1
- cmp.w #"31",d1
- beq .is31k
- bra .no31k
-
- .cgfx
-
- ; CybergraphX test
-
- move.l pb_GfxLib(a5),a0
- cmp.w #39,LIB_VERSION(a0)
- beq .known
- cmp.w #40,LIB_VERSION(a0)
- beq .known
- bra .no31k
- .known
- move.l gb_copinit(a0),a0
- cmp.w #$01FC,copinit_fm0(a0) ;Security check (test if really FMODE)
- bne .is31k ;Probably an ECS machine.
- ;Assume the user is clever enough
- ;to use "AddAudioModes DBLSCAN"....
- move.w copinit_fm0+2(a0),d0
- and.w #$c000,d0 ;Mask sprite and bitplane double bit
- beq .no31k
- .is31k
- moveq #TRUE,d0
- bra .exit
- .no31k
- moveq #FALSE,d0
- .exit
- popm d2-d7/a2-a6
- rts
- .picasso96
- dc.b "Picasso96",0
- .p96amigavideo
- dc.b "Picasso96/AmigaVideo",0
- even
-
- ;in:
- * d0 Frequency
- ;out:
- * d0 Closest frequency
- * d1 Index
- findfreq:
- lea freqlist(pc),a0
- cmp.l (a0),d0
- bls.b .2
- .findfreq
- cmp.l (a0)+,d0
- bhi.b .findfreq
- move.l -4(a0),d1
- sub.l d0,d1
- sub.l -8(a0),d0
- cmp.l d1,d0
- bhs.b .1
- subq.l #4,a0
- .1
- subq.l #4,a0
- .2
- move.l (a0),d0
- move.l a0,d1
- sub.l #freqlist,d1
- lsr.l #2,d1
- rts
-
- freqlist:
- dc.l 4410 ; CD/10
- dc.l 4800 ; DAT/10
- dc.l 5513 ; CD/8
- dc.l 6000 ; DAT/8
- dc.l 7350 ; CD/6
- dc.l 8000 ; µ- and A-Law, DAT/6
- dc.l 9600 ; DAT/5
- dc.l 11025 ; CD/4
- dc.l 12000 ; DAT/4
- dc.l 14700 ; CD/3
- dc.l 16000 ; DAT/3
- dc.l 17640 ; CD/2.5
- dc.l 18900
- dc.l 19200 ; DAT/2.5
- dc.l 22050 ; CD/2
- dc.l 24000 ; DAT/2
- dc.l 27429
- FREQUENCIES_OCS EQU (*-freqlist)>>2
- dc.l 29400 ; CD/1.5
- dc.l 32000 ; DAT/1.5
- dc.l 33075
- dc.l 37800
- dc.l 44100 ; CD
- dc.l 48000 ; DAT
- FREQUENCIES EQU (*-freqlist)>>2
- dc.l -1
-
- * _CreateTable directly stolen from Christian Buchner's CyberSound
- * audio sub system (with permission).
-
- * _CreateTable **************************************************************
-
- ; Parameters
-
- ; a0 = Table address
- ; (MUST have enough space for 65536 UWORDS)
- ; a1 = Additive Array
- ; 256 UBYTEs
- ;
- ; the table is organized as follows:
- ; 32768 UWORDS positive range, ascending order
- ; 32768 UWORDS negative range, ascending order
- ; access: (a0,d0.l*2)
- ; where d0.w is signed word sample data
- ; and the upper word of d0.l is *cleared!*
-
-
- _CreateTable movem.l a2/d2-d6,-(sp)
-
- lea 128(a1),a2
-
- move.l a2,a1 ; count the number of steps
- moveq #128-1,d0 ; in the positive range
- moveq #0,d5
- .countpositive move.b (a1)+,d1
- ext.w d1
- ext.l d1
- add.l d1,d5
- dbra d0,.countpositive ; d5=number of steps
- move.l #32768,d6 ; reset stretch counter
-
- move.l a2,a1 ; middle value in calibdata
- move.w #32768-1,d0 ; number of positive values -1
- moveq #0,d1 ; HI value
- moveq #0,d2 ; LO value
- moveq #0,d3 ; counter
- .fetchnext2 move.b (a1)+,d4 ; add calibtable to counter
- ext.w d4
- add.w d4,d3
- .outerloop2 tst.w d3
- bgt.s .positive2
- .negative2 addq.w #1,d1 ; increment HI value
- sub.w d4,d2 ; reset LO value
- bra.s .fetchnext2
- .positive2 move.b d1,(a0)+ ; store HI and LO value
- move.b d2,(a0)+
- sub.l d5,d6 ; stretch the table
- bpl.s .repeat2 ; to 32768 entries
- add.l #32768,d6
- addq.w #1,d2 ; increment LO value
- subq.w #1,d3 ; decrement counter
- .repeat2 dbra d0,.outerloop2
-
- move.l a2,a1 ; count the number of steps
- moveq #128-1,d0 ; in the negative range
- moveq #0,d5
- .countnegative move.b -(a1),d1
- ext.w d1
- ext.l d1
- add.l d1,d5
- dbra d0,.countnegative ; d5=number of steps
- move.l #32768,d6 ; reset stretch counter
-
- add.l #2*32768,a0 ; place at the end of the table
- move.l a2,a1 ; middle value in calibdata
- move.w #32768-1,d0 ; number of negative values -1
- moveq #-1,d1 ; HI value
- moveq #-1,d2 ; LO value
- moveq #0,d3 ; counter
- .fetchnext1 move.b -(a1),d4 ; add calibtable to counter
- ext.w d4
- add.w d4,d3
- add.w d4,d2 ; maximize LO value
- .outerloop1 tst.w d3
- bgt.s .positive1
- .negative1 subq.w #1,d1
- bra.s .fetchnext1
- .positive1 move.b d2,-(a0) ; store LO and HI value
- move.b d1,-(a0)
- sub.l d5,d6 ; stretch the table
- bpl.s .repeat1 ; to 32768 entries
- add.l #32768,d6
- subq.w #1,d2 ; decrement lo value
- subq.w #1,d3 ; decrement counter
- .repeat1 dbra d0,.outerloop1
-
- movem.l (sp)+,a2/d2-d6
- rts
-
-
- ****** [driver].audio/AHIsub_FreeAudio **************************************
- *
- * NAME
- * AHIsub_FreeAudio -- Deallocates the audio hardware.
- *
- * SYNOPSIS
- * AHIsub_FreeAudio( audioctrl );
- * A2
- *
- * void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * Deallocate the audio hardware and other resources allocated in
- * AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
- * 'ahi.device' before this call is made.
- *
- * INPUTS
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * NOTES
- * It must be safe to call this routine even if AHIsub_AllocAudio()
- * was never called, failed or called more than once.
- *
- * SEE ALSO
- * AHIsub_AllocAudio()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_FreeAudio:
- pushm d2-d7/a2-a6
-
- move.l a6,a5
- move.l pb_SysLib(a5),a6
-
- move.l ahiac_DriverData(a2),d0
- beq .nopaula
- move.l d0,a3
-
- move.l p_CalibrationTable(a3),d0
- beq.b .notable
- move.l d0,a1
- call FreeVec
- .notable
- tst.l p_audiodev(a3)
- bne.b .noaudiodev
- move.l p_audioreq(a3),a1
- move.w #CMD_RESET,IO_COMMAND(a1) ;Restore audio interrupts
- bsr.w BeginIO
- move.l p_audioport(a3),a0
- call WaitPort
- move.l p_audioport(a3),a0
- call GetMsg
- move.l p_audioreq(a3),a1
- subq.l #1,p_audiodev(a3)
- call CloseDevice
- .noaudiodev
- move.l p_audioreq(a3),d0
- beq.b .noaudioreq
- move.l d0,a1
- call FreeVec
- .noaudioreq
- move.l p_audioport(a3),d0
- beq.b .noaudioport
- move.l d0,a0
- call DeleteMsgPort
- .noaudioport
- tst.l p_AuraAddress(a3)
- beq .noaura
- move.l pb_CardResource(a5),d0
- beq .noaura
- move.l d0,a6
- move.l p_CardHandle(a3),d0
- beq .noaura
- move.l d0,a1
- call EndCardAccess
- move.l p_CardHandle(a3),a1
- moveq #CARDF_REMOVEHANDLE,d0
- call ReleaseCard
- .noaura
- move.l pb_SysLib(a5),a6
- move.l p_CardHandle(a3),d0
- beq .nocardhandle
- move.l d0,a1
- call FreeVec
- .nocardhandle
- move.l pb_MiscResource(a5),a6
- tst.l p_ParPortUser(a3)
- bne.b .noparport
- moveq #MR_PARALLELPORT,d0
- jsr MR_FREEMISCRESOURCE(a6)
- .noparport
- tst.l p_ParBitsUser(a3)
- bne.b .noparbits
- moveq #MR_PARALLELBITS,d0
- jsr MR_FREEMISCRESOURCE(a6)
- .noparbits
- tst.l p_SerBitsUser(a3)
- bne.b .noserbits
- moveq #MR_SERIALBITS,d0
- jsr MR_FREEMISCRESOURCE(a6)
- .noserbits
- move.l pb_SysLib(a5),a6
- move.l a3,a1
- clr.l ahiac_DriverData(a2)
- call FreeVec
- .nopaula
- moveq #0,d0
- popm d2-d7/a2-a6
- rts
-
-
- ****** [driver].audio/AHIsub_Disable ****************************************
- *
- * NAME
- * AHIsub_Disable -- Temporary turn off audio interrupt/task
- *
- * SYNOPSIS
- * AHIsub_Disable( audioctrl );
- * A2
- *
- * void AHIsub_Disable( struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * If you are lazy, then call exec.library/Disable().
- * If you are smart, only disable your own interrupt or task.
- *
- * INPUTS
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * NOTES
- * This call should be guaranteed to preserve all registers.
- * This call nests.
- *
- * SEE ALSO
- * AHIsub_Enable(), exec.library/Disable()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_Disable:
- push a3
- move.l ahiac_DriverData(a2),a3
- addq.w #1,p_DisableCount(a3)
- move.w #INTF_AUD0,custom+INTENA
- pop a3
- rts
-
- ****** [driver].audio/AHIsub_Enable *****************************************
- *
- * NAME
- * AHIsub_Enable -- Turn on audio interrupt/task
- *
- * SYNOPSIS
- * AHIsub_Enable( audioctrl );
- * A2
- *
- * void AHIsub_Enable( struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * If you are lazy, then call exec.library/Enable().
- * If you are smart, only enable your own interrupt or task.
- *
- * INPUTS
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * NOTES
- * This call should be guaranteed to preserve all registers.
- * This call nests.
- *
- * SEE ALSO
- * AHIsub_Disable(), exec.library/Enable()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_Enable:
- push a3
- move.l ahiac_DriverData(a2),a3
- subq.w #1,p_DisableCount(a3)
- bne.b .exit
- move.w #INTF_SETCLR|INTF_AUD0,custom+INTENA
- .exit
- pop a3
- rts
-
- ****** [driver].audio/AHIsub_Start ******************************************
- *
- * NAME
- * AHIsub_Start -- Starts playback or recording
- *
- * SYNOPSIS
- * error = AHIsub_Start( flags, audioctrl );
- * D0 D0 A2
- *
- * ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * What to do depends what you returned in AHIsub_AllocAudio().
- *
- * * First, assume bit AHISB_PLAY in flags is set. This means that you
- * should begin playback.
- *
- * - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
- *
- * A) Allocate a mixing buffer of ahiac_BuffSize bytes. The buffer must
- * be long aligned!
- * B) Create/start an interrupt or task that will do 1-6 over and over
- * again until AHIsub_Stop() is called. Note that it is not a good
- * idea to do the actual mixing and conversion in a real hardware
- * interrupt. Signal a task or create a Software Interrupt to do
- * the number crunching.
- *
- * 1) Call the user Hook ahiac_PlayerFunc with the following parameters:
- * A0 - (struct Hook *)
- * A2 - (struct AHIAudioCtrlDrv *)
- * A1 - Set to NULL.
- *
- * 2) [Call the ahiac_PreTimer function. If it returns TRUE (Z will be
- * cleared so you don't have to test d0), skip step 3 and 4. This
- * is used to avoid overloading the CPU. This step is optional.
- * A2 is assumed to point to struct AHIAudioCtrlDrv. All registers
- * except d0 are preserved. (V4)]
- *
- * 3) Call the mixing Hook (ahiac_MixerFunc) with the following
- * parameters:
- * A0 - (struct Hook *) - The Hook itself
- * A2 - (struct AHIAudioCtrlDrv *)
- * A1 - (WORD *[]) - The mixing buffer.
- * Note that ahiac_MixerFunc preserves ALL registers.
- * The user Hook ahiac_SoundFunc will be called by the mixing
- * routine when a sample have been processed, so you don't have to
- * worry about that.
- * How the buffer will be filled is indicated by ahiac_Flags.
- * It is always filled with signed 16-bit (32 bit if AHIACB_HIFI in
- * in ahiac_Flags is set) words, even if playback is 8 bit. If
- * AHIDBB_STEREO is set (in ahiac_Flags), data for left and right
- * channel are interleaved:
- * 1st sample left channel,
- * 1st sample right channel,
- * 2nd sample left channel,
- * ...,
- * ahiac_BuffSamples:th sample left channel,
- * ahiac_BuffSamples:th sample right channel.
- * If AHIDBB_STEREO is cleared, the mono data is stored:
- * 1st sample,
- * 2nd sample,
- * ...,
- * ahiac_BuffSamples:th sample.
- * Note that neither AHIACB_STEREO nor AHIACB_HIFI will be set if
- * you didn't report that you understand these flags when
- * AHI_AllocAudio() was called.
- *
- * For AHI V2, the type of buffer is also available in ahiac_BuffType.
- * It is suggested that you use this value instead. ahiac_BuffType
- * can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S and AHIST_S32S.
- *
- * 4) Convert the buffer if needed and feed it to the audio hardware.
- * Note that you may have to clear CPU caches if you are using DMA
- * to play the buffer, and the buffer is not allocated in non-
- * cachable RAM.
- *
- * 5) [Call the ahiac_PostTimer function. A2 is assumed to point to
- * struct AHIAudioCtrlDrv. All registers are preserved. (V4)]
- *
- * 6) Wait until the whole buffer has been played, then repeat.
- *
- * Use double buffering if possible!
- *
- * You may DECREASE ahiac_BuffSamples slightly, for example to force an
- * even number of samples to be mixed. By doing this you will make
- * ahiac_PlayerFunc to be called at wrong frequency so be careful!
- * Even if ahiac_BuffSamples is defined ULONG, it will never be greater
- * than 65535.
- *
- * ahiac_BuffSize is the largest size of the mixing buffer that will be
- * needed until AHIsub_Stop() is called.
- *
- * ahiac_MaxBuffSamples is the maximum number of samples that will be
- * mixed (until AHIsub_Stop() is called). You can use this value if you
- * need to allocate DMA buffers.
- *
- * ahiac_MinBuffSamples is the minimum number of samples that will be
- * mixed. Most drivers will ignore it.
- *
- * If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
- * ahiac_BuffSize is large enough to hold two buffers. The mixing buffer
- * will be filled with the wet buffer first, immediately followed by the
- * dry buffer. I.e., ahiac_BuffSamples sample frames wet data, then
- * ahiac_BuffSamples sample frames dry data. The DSP fx should only be
- * applied to the wet buffer, and the two buffers should then be added
- * together. (V4)
- *
- * - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
- * except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
- * ahiac_PlayerFreq times per second, clocked by timers on your sound
- * card or by using 'realtime.library'. No other Amiga resources may
- * be used for timing (like direct CIA timers).
- * ahiac_MinBuffSamples and ahiac_MaxBuffSamples are undefined if
- * AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit not set).
- *
- * - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
- * the AHISB_TIMING bit set, then just start playback. Don't forget to
- * call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
- * own timing hardware or 'realtime.library' may be used. Note that
- * ahiac_MixerFunc, ahiac_BuffSamples, ahiac_MinBuffSamples,
- * ahiac_MaxBuffSamples and ahiac_BuffSize are undefined. ahiac_MixFreq
- * is the frequency the user wants to use for recording, if you support
- * that.
- *
- * * Second, assume bit AHISB_RECORD in flags is set. This means that you
- * should start to sample. Create a interrupt or task that does the
- * following:
- *
- * Allocate a buffer (you chose size, but try to keep it reasonable
- * small to avoid delays - it is suggested that RecordFunc is called
- * at least 4 times/second for the lowers sampling rate, and more often
- * for higher rates), and fill it with the sampled data. The buffer must
- * be long aligned, and it's size must be evenly divisible by four.
- * The format should always be AHIST_S16S (even with 8 bit mono samplers),
- * which means:
- * 1st sample left channel,
- * 1st sample right channel (same as prev. if mono),
- * 2nd sample left channel,
- * ... etc.
- * Each sample is a signed word (WORD). The sample rate should be equal
- * to the mixing rate.
- *
- * Call the ahiac_SamplerFunc Hook with the following parameters:
- * A0 - (struct Hook *) - The Hook itself
- * A2 - (struct AHIAudioCtrlDrv *)
- * A1 - (struct AHIRecordMessage *)
- * The message should be filled as follows:
- * ahirm_Type - Set to AHIST_S16S.
- * ahirm_Buffer - A pointer to the filled buffer.
- * ahirm_Samples - How many sample frames stored.
- * You must not destroy the buffer until next time the Hook is called.
- *
- * Repeat until AHIsub_Stop() is called.
- *
- * * Note that both bits may be set when this function is called.
- *
- * INPUTS
- * flags - See <libraries/ahi_sub.h>.
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * RESULT
- * Returns AHIE_OK if successful, else an error code as defined
- * in <devices/ahi.h>. AHIsub_Stop() will always be called, even
- * if this call failed.
- *
- * NOTES
- * The driver must be able to handle multiple calls to this routine
- * without preceding calls to AHIsub_Stop().
- *
- * SEE ALSO
- * AHIsub_Update(), AHIsub_Stop()
- *
- *****************************************************************************
- *
- *
- *
-
- AHIsub_Start:
- pushm d2-d7/a2-a6
-
- move.l d0,d7
- lea custom,a4
- move.l ahiac_DriverData(a2),a3
-
- btst #AHISB_PLAY,d7
- beq .dont_play
-
- **
- *** AHISB_PLAY
- **
- moveq #AHISF_PLAY,d0
- call AHIsub_Stop ;Stop current playback if any.
- call AHIsub_Update ;fill variables
-
- move.l a6,a5
- move.l pb_SysLib(a5),a6
-
- move.l ahiac_BuffSize(a2),d0
- move.l #MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_Mixbuffer(a3)
- beq .error_nomem
-
- move.l ahiac_MixFreq(a2),d1
- bsr.w calcperiod
- move.w d1,p_AudPer(a3)
-
- * The init*bit? routines allocates p_DMAbuffer, sets up
- * p_AudPtr, sets the volume, stores the correct interrupt routines in
- * p_PlayInt's and p_PlaySoftInt's IS_CODE.
-
- pea .1(pc)
- move.b p_Flags(a3),d0
- and.b #PF_STEREO|PF_14BIT,d0
- beq.w init8bitM
- cmp.b #PF_STEREO,d0
- beq.w init8bitS
- cmp.b #PF_14BIT,d0
- beq.w init14bitM
- bra.w init14bitS
- .1
- tst.l d0
- bne .exit
-
- * Install play interrupt
- lea p_PlayInt(a3),a1
- moveq #INTB_AUD0,d0
- call SetIntVector
- clr.w p_DisableCount(a3)
-
- move.w #INTF_SETCLR|INTF_AUD0,INTENA(a4) ;enable
- move.w #INTF_SETCLR|INTF_AUD0,INTREQ(a4) ;start
-
- move.l a5,a6
-
-
- .dont_play
- btst #AHISB_RECORD,d7
- beq .dont_record
- **
- *** AHISB_RECORD
- **
- btst #PB_14BIT,p_Flags(a3) ;Sanity check...
- bne .error_unknown
-
- moveq #AHISF_RECORD,d0
- call AHIsub_Stop ;Stop current recording if any.
-
- move.l a6,a5
- move.l pb_SysLib(a5),a6
-
- move.l #RECORDSAMPLES*4,d0
- move.l #MEMF_PUBLIC,d1
- call AllocVec
- move.l d0,p_RecBuffer1(a3)
- beq .error_nomem
-
- move.l d0,p_RecFillPtr(a3)
- move.w #RECORDSAMPLES,p_RecFillCount(a3)
-
- move.l #RECORDSAMPLES*4,d0
- move.l #MEMF_PUBLIC,d1
- call AllocVec
- move.l d0,p_RecBuffer2(a3)
- beq .error_nomem
-
- move.l ahiac_MixFreq(a2),d1
- bsr.w calcperiod
- lsr.w #1,d1 ;Period/2 => Frequency·2
- move.w d1,AUD2PER(a4)
- move.w d1,AUD3PER(a4)
- move.w p_MonitorVolume(a3),d0
- move.w d0,AUD2VOL(a4)
- move.w d0,AUD3VOL(a4)
-
- * Install record interrupt
- move.w p_Input(a3),d0
- beq .parsampler
- cmp.w #1,d0
- beq .aurasampler
- cmp.w #2,d0
- beq .clarity
- bra .error_unknown
-
- .parsampler
- tst.b p_Parallel(a3) ;Parrallel port allocated?
- beq .error_unknown
- lea p_RecIntData(a3),a1
- move.l a1,IS_DATA+p_RecInt(a3)
- move.l #RecordInterrupt,IS_CODE+p_RecInt(a3)
-
- move.b #$ff,_ciab+ciaddrb ; Set parallel port to output
-
- bra .setrecint
-
- .clarity
- tst.b p_Parallel(a3) ;Parrallel port allocated?
- beq .error_unknown
-
- move.l pb_MiscResource(a5),a6
- move.l #MR_SERIALBITS,d0 ; allocate serial port control lines
- lea IDString(pc),a1
- jsr MR_ALLOCMISCRESOURCE(a6)
- move.l d0,p_SerBitsUser(a3)
- bne .error_unknown
-
- lea p_RecIntData(a3),a1
- move.l a1,IS_DATA+p_RecInt(a3)
- move.l #RecordInterruptClarity,IS_CODE+p_RecInt(a3)
-
- ; Set DTR, PRTBUSY and PRTRPOUT to outputs
- or.b #CIAF_COMDTR!CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciaddra
- move.b #$ff,_ciab+ciaddrb ; Set parallel port to output
- ; Reset Clarity
- move.b #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
- move.b #CIAF_PRTRPOUT,_ciab+ciapra
- move.b #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
- ; Clarity is now in stereo record mode
-
- bra .setrecint
-
- .aurasampler
- tst.l p_AuraAddress(a3) ;Aura sampler allocated?
- beq .error_unknown
- lea p_RecIntDataAura(a3),a1
- move.l a1,IS_DATA+p_RecInt(a3)
- move.l #RecordInterruptAura,IS_CODE+p_RecInt(a3)
- bra .setrecint
-
- .setrecint
- move.l pb_SysLib(a5),a6
- lea p_RecInt(a3),a1
- moveq #INTB_AUD3,d0
- call SetIntVector
-
- move.w #DMAF_AUD2|DMAF_AUD3,DMACON(a4) ;disable DMA
- move.w #INTF_SETCLR|INTF_AUD3,INTENA(a4) ;enable
- move.w #INTF_SETCLR|INTF_AUD3,INTREQ(a4) ;start
-
- .dont_record
- .return
- moveq #AHIE_OK,d0
- .exit
- popm d2-d7/a2-a6
- rts
- .error_nomem
- moveq #AHIE_NOMEM,d0
- bra.b .exit
- .error_unknown
- moveq #AHIE_UNKNOWN,d0
- bra.b .exit
-
-
- ;in:
- * a2 AudioCtrl
- * a3 paula
- * a4 custom
- * a5 paulaBase
- * a6 ExecBase
- init8bitM:
- PRINTF 2,"init8bitM()"
- move.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
- move.l #SoftInt_8bitM,IS_CODE+p_PlaySoftInt(a3)
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi
- move.l #SoftInt_8bitMH,IS_CODE+p_PlaySoftInt(a3)
- .nohifi
-
- move.l p_MinBufferLength(a3),d0
- add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
- addq.l #3,d0
- and.b #~3,d0 ;make it a multiple of 4
- move.l d0,d2 ;d2 = channel size
-
- lsl.l #1,d0 ;Double buffer
- move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_DMAbuffer(a3)
- beq .nomem
-
- move.l d0,p_AudPtr1A(a3)
- move.l d0,p_AudPtr2A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr1B(a3)
- move.l d0,p_AudPtr2B(a3)
-
- ; move.w #64,AUD0VOL(a4)
- ; move.w #64,AUD1VOL(a4)
-
- moveq #0,d0
- rts
- .nomem
- moveq #AHIE_NOMEM,d0
- rts
-
- ;in:
- * a2 AudioCtrl
- * a3 paula
- * a5 paulaBase
- * a6 ExecBase
- init8bitS:
- PRINTF 2,"init8bitS()"
- move.l #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
- move.l #SoftInt_8bitS,IS_CODE+p_PlaySoftInt(a3)
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi
- move.l #SoftInt_8bitSH,IS_CODE+p_PlaySoftInt(a3)
- .nohifi
-
- move.l p_MinBufferLength(a3),d0
- add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 8 bit samples
- addq.l #3,d0
- and.b #~3,d0 ;make it a multiple of 4
- move.l d0,d2 ;d2 = channel size
-
- lsl.l #2,d0 ;Double buffer + Stereo
- move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_DMAbuffer(a3)
- beq .nomem
-
- move.l d0,p_AudPtr1A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr2A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr1B(a3)
- add.l d2,d0
- move.l d0,p_AudPtr2B(a3)
-
- ; move.w #64,AUD0VOL(a4)
- ; move.w #64,AUD1VOL(a4)
-
- moveq #0,d0
- rts
- .nomem
- moveq #AHIE_NOMEM,d0
- rts
-
- ;in:
- * a2 AudioCtrl
- * a3 paula
- * a5 paulaBase
- * a6 ExecBase
- init14bitM:
- PRINTF 2,"init14bitM()"
- move.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
- lea SoftInt_14bitM(pc),a0
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi1
- lea SoftInt_14bitMH(pc),a0
- .nohifi1
- tst.l p_CalibrationTable(a3)
- beq.b .nocalib
- lea SoftInt_14CbitM(pc),a0
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi2
- lea SoftInt_14CbitMH(pc),a0
- .nohifi2
- .nocalib
- move.l a0,IS_CODE+p_PlaySoftInt(a3)
-
- move.l p_MinBufferLength(a3),d0
- add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
- addq.l #3,d0
- and.b #~3,d0 ;make it a multiple of 4
- move.l d0,d2 ;d2 = channel size
-
- lsl.l #2,d0 ;Double buffer + 2×8 bit
- move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_DMAbuffer(a3)
- beq .nomem
-
- move.l d0,p_AudPtr1A(a3)
- move.l d0,p_AudPtr2A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr4A(a3)
- move.l d0,p_AudPtr3A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr1B(a3)
- move.l d0,p_AudPtr2B(a3)
- add.l d2,d0
- move.l d0,p_AudPtr4B(a3)
- move.l d0,p_AudPtr3B(a3)
-
- ; move.w #64,AUD0VOL(a4)
- ; move.w #64,AUD1VOL(a4)
- ; move.w #1,AUD2VOL(a4)
- ; move.w #1,AUD3VOL(a4)
-
- moveq #0,d0
- rts
- .nomem
- moveq #AHIE_NOMEM,d0
- rts
-
- ;in:
- * a2 AudioCtrl
- * a3 paula
- * a5 paulaBase
- * a6 ExecBase
- init14bitS:
- PRINTF 2,"init14bitS()"
- move.l #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
- lea SoftInt_14bitS(pc),a0
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi1
- lea SoftInt_14bitSH(pc),a0
- .nohifi1
- tst.l p_CalibrationTable(a3)
- beq.b .nocalib
- lea SoftInt_14CbitS(pc),a0
- move.b p_Flags(a3),d0
- btst #PB_HIFI,d0
- beq .nohifi2
- lea SoftInt_14CbitSH(pc),a0
- .nohifi2
- .nocalib
- move.l a0,IS_CODE+p_PlaySoftInt(a3)
-
- move.l p_MinBufferLength(a3),d0
- add.l ahiac_MaxBuffSamples(a2),d0 ;Max. # of 16 bit samples
- addq.l #3,d0
- and.b #~3,d0 ;make it a multiple of 4
- move.l d0,d2 ;d2 = channel size
-
- lsl.l #3,d0 ;Double buffer + 2×8 bit + Stereo
- move.l #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
- call AllocVec
- move.l d0,p_DMAbuffer(a3)
- beq .nomem
-
- move.l d0,p_AudPtr1A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr2A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr3A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr4A(a3)
- add.l d2,d0
- move.l d0,p_AudPtr1B(a3)
- add.l d2,d0
- move.l d0,p_AudPtr2B(a3)
- add.l d2,d0
- move.l d0,p_AudPtr3B(a3)
- add.l d2,d0
- move.l d0,p_AudPtr4B(a3)
-
- ; move.w #64,AUD0VOL(a4)
- ; move.w #64,AUD1VOL(a4)
- ; move.w #1,AUD2VOL(a4)
- ; move.w #1,AUD3VOL(a4)
-
- moveq #0,d0
- rts
- .nomem
- moveq #AHIE_NOMEM,d0
- rts
-
- ****** [driver].audio/AHIsub_Update *****************************************
- *
- * NAME
- * AHIsub_Update -- Update some variables
- *
- * SYNOPSIS
- * AHIsub_Update( flags, audioctrl );
- * D0 A2
- *
- * void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * All you have to do is to update some variables:
- * Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
- * ahiac_BuffSamples (and perhaps ahiac_PlayerFreq if you use it).
- * Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc and
- * ahiac_PlayerFreq.
- * Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc and ahiac_PlayerFreq.
- *
- * INPUTS
- * flags - Currently no flags defined.
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * RESULT
- *
- * NOTES
- * This call must be safe from interrupts.
- *
- * SEE ALSO
- * AHIsub_Start()
- *
- *****************************************************************************
- *
- *
- *
-
- AHIsub_Update:
- pushm d2-d7/a2-a6
-
- call AHIsub_Disable ;make sure we don't get an interrupt
- ;while updating our local variables
- move.l ahiac_DriverData(a2),a3
-
- move.l ahiac_PlayerFunc(a2),a0
- move.l a0,p_PlayerHook(a3)
- move.l h_Entry(a0),p_PlayerEntry(a3)
-
- move.l ahiac_BuffSamples(a2),d1
- and.b #~3,d1 ;make it a multiple of 4
- move.l d1,ahiac_BuffSamples(a2)
- move.l d1,d0
- lsr.l #2,d0
- subq.l #1,d0
- move.l d0,p_LoopTimes(a3) ;See softints. (Unrolled)
-
- PRINTF 2,"LoopTimes: %ld", d0
-
- ; move.l p_MinBufferLength(a3),d0
- ; divu.w d1,d0
- ; ext.l d0
- ; move.l d0,p_RepeatTimes(a3) ;that's really times-1 (dbf dx,label)
-
- ; PRINTF 2,"RepeatTimes: %ld", d0
-
- ; addq.l #1,d0
- ; mulu.w d1,d0
- ; lsr.l #1,d0 ;length in words
- ; move.w d0,p_AudLen(a3)
-
- ; PRINTF 2,"AudLen: %ld", d0
-
- move.l ahiac_MixerFunc(a2),a0
- move.l a0,p_MixHook(a3)
- move.l h_Entry(a0),p_MixEntry(a3)
-
- call AHIsub_Enable
- moveq #0,d0
- popm d2-d7/a2-a6
- rts
-
-
- ****** [driver].audio/AHIsub_Stop *******************************************
- *
- * NAME
- * AHIsub_Stop -- Stops playback.
- *
- * SYNOPSIS
- * AHIsub_Stop( flags, audioctrl );
- * D0 A2
- *
- * void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * Stop playback and/or recording, remove all resources allocated by
- * AHIsub_Start().
- *
- * INPUTS
- * flags - See <libraries/ahi_sub.h>.
- * audioctrl - pointer to an AHIAudioCtrlDrv structure.
- *
- * NOTES
- * It must be safe to call this routine even if AHIsub_Start() was never
- * called, failed or called more than once.
- *
- * SEE ALSO
- * AHIsub_Start()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_Stop:
- pushm d2-d7/a2-a6
-
- lea custom,a4
- move.l a6,a5
- move.l pb_SysLib(a5),a6
- move.l ahiac_DriverData(a2),a3
-
- push d0
- btst #AHISB_PLAY,d0
- beq .dontplay
-
- **
- *** AHISB_PLAY
- **
- move.w #DMAF_AUDIO,DMACON(a4) ;disable audio DMA
-
- move.w #INTF_AUD0,INTENA(a4)
- move.w #INTF_AUD0,INTREQ(a4) ;Clear any waiting interrupts
- move.l #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
- lea p_PlayInt(a3),a1
- moveq #INTB_AUD0,d0
- call SetIntVector
-
- moveq #0,d0
- move.w d0,AUD0VOL(a4)
- move.w d0,AUD1VOL(a4)
- move.w d0,AUD2VOL(a4)
- move.w d0,AUD3VOL(a4)
-
- move.l p_DMAbuffer(a3),d0
- beq.b .nodmamem
- move.l d0,a1
- clr.l p_DMAbuffer(a3)
- call FreeVec
- .nodmamem
- move.l p_Mixbuffer(a3),d0
- beq.b .nomixmem
- move.l d0,a1
- clr.l p_Mixbuffer(a3)
- call FreeVec
- .nomixmem
-
- .dontplay
- pop d0
- btst #AHISB_RECORD,d0
- beq .dontrecord
-
- **
- *** AHISB_RECORD
- **
- btst #PB_14BIT,p_Flags(a3) ;Sanity check...
- bne .dontrecord
-
- move.w #INTF_AUD3,INTENA(a4)
- move.w #INTF_AUD3,INTREQ(a4) ;Clear any waiting interrupts
-
- move.l #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
- lea p_RecInt(a3),a1
- moveq #INTB_AUD3,d0
- call SetIntVector
-
- move.w #0,AUD2VOL(a4)
- move.w #0,AUD3VOL(a4)
-
- move.l p_RecBuffer1(a3),d0
- beq.b .norecmem1
- move.l d0,a1
- clr.l p_RecBuffer1(a3)
- call FreeVec
- .norecmem1
- move.l p_RecBuffer2(a3),d0
- beq.b .norecmem2
- move.l d0,a1
- clr.l p_RecBuffer2(a3)
- call FreeVec
- .norecmem2
- .dontrecord
- .return
- moveq #0,d0
- popm d2-d7/a2-a6
- rts
-
- ****** [driver].audio/AHIsub_#? *********************************************
- *
- * NAME
- * AHIsub_SetEffect -- Set effect.
- * AHIsub_SetFreq -- Set frequency.
- * AHIsub_SetSound -- Set sound.
- * AHIsub_SetVol -- Set volume and stereo panning.
- * AHIsub_LoadSound -- Prepare a sound for playback.
- * AHIsub_UnloadSound -- Discard a sound.
- *
- * SYNOPSIS
- * See functions in 'ahi.device'.
- *
- * IMPLEMENTATION
- * If AHIsub_AllocAudio() did not return with bit AHISB_MIXING set,
- * all user calls to these function will be routed to the driver.
- *
- * If AHIsub_AllocAudio() did return with bit AHISB_MIXING set, the
- * calls will first be routed to the driver, and only handled by
- * 'ahi.device' if the driver returned AHIS_UNKNOWN. This way it is
- * possible to add effects that the sound card handles on its own, like
- * filter and echo effects.
- *
- * For what each function does, see the autodocs for 'ahi.device'.
- *
- * INPUTS
- * See functions in 'ahi.device'.
- *
- * NOTES
- * See functions in 'ahi.device'.
- *
- * SEE ALSO
- * ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
- * ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
- * ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
- *
- *
- *****************************************************************************
- *
- *
-
- AHIsub_SetVol:
- AHIsub_SetFreq:
- AHIsub_SetSound:
- AHIsub_SetEffect:
- AHIsub_LoadSound:
- AHIsub_UnloadSound:
- moveq #AHIS_UNKNOWN,d0
- rts
-
- ****** [driver].audio/AHIsub_GetAttr ****************************************
- *
- * NAME
- * AHIsub_GetAttr -- Returns information about audio modes or driver
- *
- * SYNOPSIS
- * AHIsub_GetAttr( attribute, argument, default, taglist, audioctrl );
- * D0 D0 D1 D2 A1 A2
- *
- * LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
- * struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * Return the attribute based on a tag list and an AHIAudioCtrlDrv
- * structure, which are the same that will be passed to
- * AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
- * unknown to you, return the default.
- *
- * INPUTS
- * attribute - Is really a Tag and can be one of the following:
- * AHIDB_Bits - Return how many output bits the tag list will
- * result in.
- * AHIDB_MaxChannels - Return the resulting number of channels.
- * AHIDB_Frequencies - Return how many mixing/sampling frequencies
- * you support
- * AHIDB_Frequency - Return the argument:th frequency
- * Example: You support 3 frequencies 32, 44.1 and 48 kHz.
- * If argument is 1, return 44100.
- * AHIDB_Index - Return the index which gives the frequency closest
- * to argument.
- * Example: You support 3 frequencies 32, 44.1 and 48 kHz.
- * If argument is 40000, return 1 (=> 44100).
- * AHIDB_Author - Return pointer to name of driver author:
- * "Martin 'Leviticus' Blom"
- * AHIDB_Copyright - Return pointer to copyright notice, including
- * the '©' character: "© 1996 Martin Blom" or "Public Domain"
- * AHIDB_Version - Return pointer version string, normal Amiga
- * format: "paula 1.5 (18.2.96)\r\n"
- * AHIDB_Annotation - Return pointer to an annotation string, which
- * can be several lines.
- * AHIDB_Record - Are you a sampler, too? Return TRUE or FALSE.
- * AHIDB_FullDuplex - Return TRUE or FALSE.
- * AHIDB_Realtime - Return TRUE or FALSE.
- * AHIDB_MaxPlaySamples - Normally, return the default. See
- * AHIsub_AllocAudio(), section 2.
- * AHIDB_MaxRecordSamples - Return the size of the buffer you fill
- * when recording.
- *
- * The following are associated with AHIsub_HardwareControl() and are
- * new for V2.
- * AHIDB_MinMonitorVolume
- * AHIDB_MaxMonitorVolume - Return the lower/upper limit for
- * AHIC_MonitorVolume. If unsupported but always 1.0, return
- * 1.0 for both.
- * AHIDB_MinInputGain
- * AHIDB_MaxInputGain - Return the lower/upper limit for
- * AHIC_InputGain. If unsupported but always 1.0, return 1.0 for
- * both.
- * AHIDB_MinOutputVolume
- * AHIDB_MaxOutputVolume - Return the lower/upper limit for
- * AHIC_OutputVolume.
- * AHIDB_Inputs - Return how many inputs you have.
- * AHIDB_Input - Return a short string describing the argument:th
- * input. Number 0 should be the default one. Example strings
- * can be "Line 1", "Mic", "Optical" or whatever.
- * AHIDB_Outputs - Return how many outputs you have.
- * AHIDB_Output - Return a short string describing the argument:th
- * output. Number 0 should be the default one. Example strings
- * can be "Line 1", "Headphone", "Optical" or whatever.
- * argument - extra info for some attributes.
- * default - What you should return for unknown attributes.
- * taglist - Pointer to a tag list that eventually will be fed to
- * AHIsub_AllocAudio(), or NULL.
- * audioctrl - Pointer to an AHIAudioCtrlDrv structure that eventually
- * will be fed to AHIsub_AllocAudio(), or NULL.
- *
- * NOTES
- *
- * SEE ALSO
- * AHIsub_AllocAudio(), AHIsub_HardwareControl(),
- * ahi.device/AHI_GetAudioAttrsA()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_GetAttr:
- pushm d2-d7/a2-a6
- move.l a6,a5
- move.l pb_UtilLib(a5),a6
-
-
- pushm d0-d1
- moveq #FALSE,d3
- move.l a1,a0
- move.l a1,d0
- beq .notaglist
- move.l #AHIDB_Paula14Bit,d0
- move.l d3,d1
- call GetTagData
- move.l d0,d3
- .notaglist
- popm d0-d1
-
- and.l #~(AHI_TagBaseR),d0
- cmp.l #AHIDB_Data & ~(AHI_TagBaseR),d0
- bhi .default
- sub.w #100,d0
- lsl.w #1,d0
- move.w .jt(pc,d0.w),d0
- beq .default
- jsr .jt(pc,d0.w)
-
- .exit
- popm d2-d7/a2-a6
- rts
-
- .default
- move.l d2,d0
- bra .exit
-
- .jt
- dc.w 0 ; AHIDB_AudioID
- dc.w 0 ; AHIDB_Driver
- dc.w 0 ; AHIDB_Flags
- dc.w 0 ; AHIDB_Volume
- dc.w 0 ; AHIDB_Panning
- dc.w 0 ; AHIDB_Stereo
- dc.w 0 ; AHIDB_HiFi
- dc.w 0 ; AHIDB_PingPong
- dc.w 0 ; AHIDB_MultTable
- dc.w 0 ; AHIDB_Name
- dc.w ga_Bits-.jt ; AHIDB_Bits
- dc.w 0 ; AHIDB_MaxChannels
- dc.w 0 ; AHIDB_MinMixFreq
- dc.w 0 ; AHIDB_MaxMixFreq
- dc.w ga_Record-.jt ; AHIDB_Record
- dc.w ga_Frequencies-.jt ; AHIDB_Frequencies
- dc.w 0 ; AHIDB_FrequencyArg
- dc.w ga_Frequency-.jt ; AHIDB_Frequency
- dc.w ga_Author-.jt ; AHIDB_Author
- dc.w ga_Copyright-.jt ; AHIDB_Copyright
- dc.w ga_Version-.jt ; AHIDB_Version
- dc.w ga_Annotation-.jt ; AHIDB_Annotation
- dc.w 0 ; AHIDB_BufferLen
- dc.w 0 ; AHIDB_IndexArg
- dc.w ga_Index-.jt ; AHIDB_Index
- dc.w ga_Realtime-.jt ; AHIDB_Realtime
- dc.w 0 ; AHIDB_MaxPlaySamples
- dc.w ga_MaxRecordSamples-.jt ; AHIDB_MaxRecordSample
- dc.w 0 ;
- dc.w ga_FullDuplex-.jt ; AHIDB_FullDuplex
- dc.w ga_MinMonitorVolume-.jt ; AHIDB_MinMonitorVolum
- dc.w ga_MaxMonitorVolume-.jt ; AHIDB_MaxMonitorVolum
- dc.w ga_MinInputGain-.jt ; AHIDB_MinInputGain
- dc.w ga_MaxInputGain-.jt ; AHIDB_MaxInputGain
- dc.w ga_MinOutputVolume-.jt ; AHIDB_MinOutputVolume
- dc.w ga_MaxOutputVolume-.jt ; AHIDB_MaxOutputVolume
- dc.w ga_Inputs-.jt ; AHIDB_Inputs
- dc.w 0 ; AHIDB_InputArg
- dc.w ga_Input-.jt ; AHIDB_Input
- dc.w ga_Outputs-.jt ; AHIDB_Outputs
- dc.w 0 ; AHIDB_OutputArg
- dc.w ga_Output-.jt ; AHIDB_Output
- dc.w 0 ; AHIDB_Data
-
- ga_Bits:
- moveq #14,d0
- tst.l d3
- bne .exit
- moveq #8,d0
- .exit
- rts
-
- ga_Record:
- moveq #FALSE,d0
- tst.l d3
- bne .exit
- moveq #TRUE,d0
- .exit
- rts
-
- ga_Frequencies:
- bsr checkvideo
- tst.l d0
- beq .1
- moveq #FREQUENCIES,d0
- rts
- .1
- moveq #FREQUENCIES_OCS,d0
- rts
-
- ga_Frequency:
- lsl.w #2,d1
- lea freqlist(pc),a0
- ; move.l (a0,d1.w),d1
- ; bsr calcperiod
- move.l (a0,d1.w),d0
- rts
-
- ga_Author:
- lea .author(pc),a0
- move.l a0,d0
- rts
- .author dc.b "Martin 'Leviticus' Blom",0
- even
-
- ga_Copyright:
- lea .copyright(pc),a0
- move.l a0,d0
- rts
- .copyright dc.b "Public Domain",0
- even
-
- ga_Version:
- lea IDString(pc),a0
- move.l a0,d0
- rts
-
- ga_Annotation:
- lea .anno(pc),a0
- move.l a0,d0
- rts
- .anno dc.b "14 bit routines by Christian Buchner.",0
- even
-
- ga_Index:
- move.l d1,d0
- bsr findfreq
- move.l d1,d0
- rts
-
-
- ga_Realtime:
- moveq #TRUE,d0
- rts
-
- ga_MaxRecordSamples:
- move.l #RECORDSAMPLES,d0
- rts
-
- ga_FullDuplex:
- moveq #FALSE,d0
- tst.l d3
- bne .exit
- moveq #TRUE,d0
- .exit
- rts
-
-
- ga_MinMonitorVolume:
- moveq #0,d0
- rts
-
- ga_MaxMonitorVolume:
- moveq #0,d0
- tst.l d3
- bne .exit
- move.l #$10000,d0
- .exit
- rts
-
- ga_MinInputGain:
- move.l #$10000,d0
- rts
-
- ga_MaxInputGain:
- move.l #$10000,d0
- rts
-
- ga_MinOutputVolume:
- move.l #$10000,d0
- tst.l d3
- bne .exit
- moveq #0,d0
- .exit
- rts
-
- ga_MaxOutputVolume:
- move.l #$10000,d0
- rts
-
-
- ga_Inputs:
- moveq #0,d0
- tst.l d3
- bne .exit
- moveq #3,d0
- .exit
- rts
-
- ga_Input:
- lsl.l #2,d1
- move.l .inputs(pc,d1.w),d0
- rts
- .inputs dc.l .input0
- dc.l .input1
- dc.l .input2
-
- .input0 dc.b "Parallel port sampler",0
- .input1 dc.b "Aura sampler",0
- .input2 dc.b "Clarity sampler",0
- even
-
- ga_Outputs:
- moveq #1,d0
- rts
-
- ga_Output:
- lea .output(pc),a0
- move.l a0,d0
- rts
- .output dc.b "Line",0
- even
-
-
- ****** [driver].audio/AHIsub_HardwareControl ********************************
- *
- * NAME
- * AHIsub_HardwareControl -- Modify sound card settings
- *
- * SYNOPSIS
- * AHIsub_HardwareControl( attribute, argument, audioctrl );
- * D0 D0 D1 A2
- *
- * LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
- *
- * IMPLEMENTATION
- * Set or return the state of a particular hardware component. AHI uses
- * AHIsub_GetAttr() to supply the user with limits and what tags are
- * available.
- *
- * INPUTS
- * attribute - Is really a Tag and can be one of the following:
- * AHIC_MonitorVolume - Set the input monitor volume to argument.
- * AHIC_MonitorVolume_Query - Return the current input monitor
- * volume (argument is ignored).
- *
- * AHIC_InputGain - Set the input gain to argument. (V2)
- * AHIC_InputGain_Query (V2)
- *
- * AHIC_OutputVolume - Set the output volume to argument. (V2)
- * AHIC_OutputVolume_Query (V2)
- *
- * AHIC_Input - Use the argument:th input source (default is 0). (V2)
- * AHIC_Input_Query (V2)
- *
- * AHIC_Output - Use the argument:th output destination (default
- * is 0). (V2)
- * AHIC_Output_Query (V2)
- *
- * argument - What value attribute should be set to.
- * audioctrl - Pointer to an AHIAudioCtrlDrv structure.
- *
- * RESULT
- * Return the state of selected attribute. If you were asked to set
- * something, return TRUE. If attribute is unknown to you or unsupported,
- * return FALSE.
- *
- * NOTES
- * This call must be safe from interrupts.
- *
- * SEE ALSO
- * ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
- *
- *****************************************************************************
- *
- *
-
- AHIsub_HardwareControl:
- cmp.l #AHIC_MonitorVolume,d0
- bne.b .dontsetmonvol
- move.l ahiac_DriverData(a2),a1
- lsr.l #8,d1
- lsr.l #2,d1
- move.w d1,p_MonitorVolume(a1)
- bra.b .exit
- .dontsetmonvol
- cmp.l #AHIC_MonitorVolume_Query,d0
- bne.b .dontgetmonvol
- move.l ahiac_DriverData(a2),a1
- moveq #0,d0
- move.w p_MonitorVolume(a1),d0
- lsl.l #8,d0
- lsl.l #2,d0
- bra.b .quit
- .dontgetmonvol
- cmp.l #AHIC_OutputVolume,d0
- bne.b .dontsetoutvol
- move.l ahiac_DriverData(a2),a1
- lsr.l #8,d1
- lsr.l #2,d1
- move.w d1,p_OutputVolume(a1)
- bra.b .exit
- .dontsetoutvol
- cmp.l #AHIC_OutputVolume_Query,d0
- bne.b .dontgetoutvol
- move.l ahiac_DriverData(a2),a1
- moveq #0,d0
- move.w p_OutputVolume(a1),d0
- lsl.l #8,d0
- lsl.l #2,d0
- bra.b .quit
- .dontgetoutvol
- cmp.l #AHIC_Input,d0
- bne.b .dontsetinput
- move.l ahiac_DriverData(a2),a1
- move.w d1,p_Input(a1)
- bra.b .exit
- .dontsetinput
- cmp.l #AHIC_Input_Query,d0
- bne.b .dontgetinput
- move.l ahiac_DriverData(a2),a1
- moveq #0,d0
- move.w p_Input(a1),d0
- bra.b .quit
- .dontgetinput
- moveq #FALSE,d0
- .quit
- rts
- .exit
- moveq #TRUE,d0
- rts
-
-
-
-
-
-
-
- *******************************************************************************
- *******************************************************************************
-
- Interrupt_Dummy:
- move.w #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,INTREQ(a0)
- SoftInt_Dummy:
- rts
-
- *******************************************************************************
- *******************************************************************************
-
- ;in:
- * d0 scratch
- * d1 INTENAR & INTREQR
- * a0 custom
- * a1 &(paula->p_RecIntData)
- * a5 &RecordInterrupt
- * a6 ExecBase
- RecordInterrupt:
-
- * This function will be executed up to 28000 times per second - that's once per
- * rasterline! It has to be as fast as possible.
-
- move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
- moveq #0,d0
- move.b _ciaa+ciaprb,d0 ;read parallel port
- IFGE __CPU-68020
- move.l convtable(pc,d0.w*4),d0 ;1 unsigned byte -> 2 signed words
- ELSE
- add.w d0,d0
- add.w d0,d0
- move.l convtable(pc,d0.w),d0
- ENDC
- move.w d0,AUD2DAT(a0) ;left
- move.w d0,AUD3DAT(a0) ;right
-
- move.l (a1),a5 ;p_RecFillPtr
- move.l d0,(a5)+ ;store sample in buffer
- move.l a5,(a1)+ ;update pointer
- subq.w #1,(a1) ;p_ReqFillCount
- beq ri_Filled ;branch if buffer filled
- rts
-
- convtable
- CNT SET 0
- REPT 256
- dc.b CNT-128,CNT-128,CNT-128,CNT-128
- CNT SET CNT+1
- ENDR
-
- ;in:
- * d0 scratch
- * d1 INTENAR & INTREQR
- * a0 custom
- * a1 &(paula->p_RecIntData)
- * a5 &RecordInterrupt
- * a6 ExecBase
- RecordInterruptClarity:
-
- * This function will be executed up to 28000 times per second - that's once per
- * rasterline! It has to be as fast as possible.
-
- move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
-
- lea _ciab+ciatahi,a5
-
- move.b _ciaa+ciaprb,d0 ;left lsb
- ror.l #8,d0 ;d0: L0xxxxxx
- tst.b (a5) ;3x700 kHz wait states
- tst.b (a5)
- tst.b (a5)
-
- move.b _ciaa+ciaprb,d0 ;left msb
- ror.l #8,d0 ;d0: L1L0xxxx
- tst.b (a5) ;3x700 kHz wait states
- tst.b (a5)
- tst.b (a5)
-
- move.b _ciaa+ciaprb,d0 ;right lsb
- lsl.w #8,d0 ;d0: L1L0R0xx
- tst.b (a5) ;3x700 kHz wait states
- tst.b (a5)
- tst.b (a5)
-
- move.b _ciaa+ciaprb,d0 ;right msb
- ror.w #8,d0 ;d0: L1L0R1R0
-
- move.l (a1),a5 ;p_RecFillPtr
- move.l d0,(a5)+ ;store sample in buffer
- move.l a5,(a1)+ ;update pointer
-
- move.w d0,d1
- lsr.w #8,d0
- move.b d0,d1
-
- move.w d1,AUD2DAT(a0) ;right
- move.w d1,AUD3DAT(a0) ;left
-
- subq.w #1,(a1) ;p_ReqFillCount
- beq ri_Filled ;branch if buffer filled
- rts
-
- ;in:
- * d0 scratch
- * d1 INTENAR & INTREQR
- * a0 custom
- * a1 &(paula->p_RecIntDataAura)
- * a5 &RecordInterrupt
- * a6 ExecBase
- RecordInterruptAura:
-
- * This function will be executed up to 28000 times per second - that's once per
- * rasterline! It has to be as fast as possible.
-
- move.w #INTF_AUD2|INTF_AUD3,INTREQ(a0) ;Clear the interrupt flags
- move.l (a1)+,a5
- move.l (a5),d0 ;read aura sampler
- eor.l #$80008000,d0
- move.l (a1),a5 ;p_RecFillPtr
- move.l d0,(a5)+ ;store sample in buffer
- move.l a5,(a1)+ ;update pointer
-
- move.w d0,d1
- lsr.w #8,d0
- move.b d0,d1
-
- move.w d1,AUD2DAT(a0) ;left
- move.w d1,AUD3DAT(a0) ;right
-
- subq.w #1,(a1) ;p_ReqFillCount
- beq ri_Filled ;branch if buffer filled
- rts
-
- *******************************************************************************
-
- ri_Filled:
-
- * This part is only executed every RECORDSAMPLES:th time... No need to hurry.
-
- move.l 8(a1),d0 ;p_RecBuffer2->
- move.l 4(a1),8(a1) ;p_RecBuffer1->p_RecBuffer2
- move.l d0,4(a1) ; ->p_RecBuffer1
- move.l d0,-4(a1) ;p_RecFillPtr
- move.w #RECORDSAMPLES,(a1) ;p_ReqFillCount
- move.l 12(a1),a1 ;p_RecSoftIntPtr
- jmp _LVOCause(a6)
-
-
- ;in:
- * d0 scratch
- * d1 scratch
- * a0 scratch
- * a1 struct paula *
- * a5 scratch
- RecordSoftInt:
-
- * This function is not executed many times per second and is therefore not
- * fully optimized... ;)
- push a2
- move.w p_MonitorVolume(a1),d0
- move.w d0,custom+AUD2VOL
- move.w d0,custom+AUD3VOL
- move.l p_RecBuffer2(a1),p_rmBuffer(a1)
- move.l p_AudioCtrl(a1),a2
- lea p_RecordMessage(a1),a1
- move.l ahiac_SamplerFunc(a2),a0
- move.l h_Entry(a0),a5
- jsr (a5)
- pop a2
- rts
-
- *******************************************************************************
- *******************************************************************************
-
- ;in:
- * d0 scratch
- * d1 INTENAR & INTREQR
- * a0 custom
- * a1 struct paula *
- * a5 &AudioInterrupt
- * a6 ExecBase
-
- AudioInterrupt2: ;Two hardware channels used
- ; move.l p_AudLenPer(a1),d0
- ; move.l d0,AUD0LEN(a0)
- ; move.l d0,AUD1LEN(a0)
- move.w p_AudPer(a1),d0
- move.w d0,AUD0PER(a0)
- move.w d0,AUD1PER(a0)
- move.w p_OutputVolume(a1),AUD0VOL(a0)
- move.w p_OutputVolume(a1),AUD1VOL(a0)
-
- move.l p_DoubleBufferOffset(a1),d0
- eor.w #4*4,d0
- move.l d0,p_DoubleBufferOffset(a1)
-
- lea p_AudPtrs(a1,d0.l),a5
- tst.w p_SwapChannels(a1)
- bne .swap
- move.l (a5)+,AUD0LC(a0)
- move.l (a5)+,AUD1LC(a0)
- bra .1
- .swap
- move.l (a5)+,AUD1LC(a0)
- move.l (a5)+,AUD0LC(a0)
- .1
- lea p_PlaySoftInt(a1),a1
- move.w #INTF_AUD0,INTREQ(a0) ;Clear the interrupt
- jmp _LVOCause(a6) ;start PlaySoftInt
-
-
- AudioInterrupt4: ;Four hardware channels used
- ; move.l p_AudLenPer(a1),d0
- ; move.l d0,AUD0LEN(a0)
- ; move.l d0,AUD1LEN(a0)
- ; move.l d0,AUD2LEN(a0)
- ; move.l d0,AUD3LEN(a0)
- move.w p_AudPer(a1),d0
- move.w d0,AUD0PER(a0)
- move.w d0,AUD1PER(a0)
- move.w d0,AUD2PER(a0)
- move.w d0,AUD3PER(a0)
- move.w #64,AUD0VOL(a0)
- move.w #64,AUD1VOL(a0)
- move.w #1,AUD2VOL(a0)
- move.w #1,AUD3VOL(a0)
-
- move.l p_DoubleBufferOffset(a1),d0
- eor.w #4*4,d0
- move.l d0,p_DoubleBufferOffset(a1)
-
- lea p_AudPtrs(a1,d0.l),a5
- tst.w p_SwapChannels(a1)
- bne .swap
- move.l (a5)+,AUD0LC(a0)
- move.l (a5)+,AUD1LC(a0)
- move.l (a5)+,AUD2LC(a0)
- move.l (a5)+,AUD3LC(a0)
- bra .1
- .swap
- move.l (a5)+,AUD1LC(a0)
- move.l (a5)+,AUD0LC(a0)
- move.l (a5)+,AUD3LC(a0)
- move.l (a5)+,AUD2LC(a0)
- .1
- lea p_PlaySoftInt(a1),a1
- move.w #INTF_AUD0,INTREQ(a0) ;Clear the interrupt
- jmp _LVOCause(a6) ;start PlaySoftInt
-
-
- *******************************************************************************
-
- ;in:
- * d0 scratch
- * d1 scratch
- * a0 scratch
- * a1 struct paula *
- * a5 scratch
-
- CONVERT_PRE MACRO
- pushm std
- move.l a1,a6
- move.l p_AudioCtrl(a6),a2
- move.l ahiac_PreTimer(a2),a0
- jsr (a0)
- move.l d0,d7
-
- move.l p_DoubleBufferOffset(a6),d0
- lea p_AudPtrs(a6,d0.l),a0
- movem.l (a0)+,d2/d3/d4/d5 ;get all 4 buffer pointers
-
- moveq #0,d6
- .repeat
- movem.l p_PlayerHookRegs(a6),a0/a1/a3
- jsr (a3) ;call Player Hook
- tst.l d7
- bne .skip
- movem.l p_MixHookRegs(a6),a0/a1/a3
- jsr (a3) ;call Mixer Hook
- move.l p_LoopTimes(a6),d0
- ENDM
-
- ;
- ; Conversion code here!
- ;
- ; d0 counter
- ; d1 scratch
- ; d2-d5 buffer pointers
- ; d6 (sample counter/4)
- ; d7 (pretimer flag)
- ; a0 scratch
- ; a1 source buffer
- ; a2 AudioCtrl
- ; a3-a5 scratch
- ; a6 struct paula *
- ;
- ; Conversion code here!
- ;
-
- CONVERT_POST MACRO
- .skip
- add.l ahiac_BuffSamples(a2),d6
- cmp.l p_MinBufferLength(a6),d6
- blo .repeat
- move.l ahiac_PostTimer(a2),a0
- jsr (a0)
- move.l d6,d0
- lea custom,a0
- popm std
- ENDM
-
- ; Exit code here
- ; d0 Samples in buffer
- ; a0 custom
-
- *******************************************************************************
-
- SoftInt_8bitM:
-
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- .loop
- move.b (a1),d1
- lsl.l #8,d1
- move.b 2(a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 6(a1),d1
- move.l d1,(a0)+
- addq.w #8,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_8bitMH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- .loop
- move.b (a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- move.l d1,(a0)+
- add.w #16,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_8bitS:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- .loop
-
- ; Left
- move.b (a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- move.l d1,(a3)+
-
- ; Right
- move.b 2(a1),d1
- lsl.l #8,d1
- move.b 6(a1),d1
- lsl.l #8,d1
- move.b 10(a1),d1
- lsl.l #8,d1
- move.b 14(a1),d1
- move.l d1,(a0)+
-
- add.w #16,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_8bitSH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- .loop
-
- ; Left
- move.b (a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 16(a1),d1
- lsl.l #8,d1
- move.b 24(a1),d1
- move.l d1,(a3)+
-
- ; Right
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- lsl.l #8,d1
- move.b 20(a1),d1
- lsl.l #8,d1
- move.b 28(a1),d1
- move.l d1,(a0)+
-
- add.w #32,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_14bitM:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- .loop
-
- ; High
- move.b (a1),d1
- lsl.l #8,d1
- move.b 2(a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 6(a1),d1
- move.l d1,(a0)+
-
- ; Low
- move.b 1(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 3(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 5(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 7(a1),d1
- lsr.b #2,d1
- move.l d1,(a5)+
-
- addq.w #8,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
- *******************************************************************************
-
-
- SoftInt_14bitMH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- .loop
-
- ; High
- move.b (a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- move.l d1,(a0)+
-
- ; Low
- move.b 1(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 5(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 9(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 13(a1),d1
- lsr.b #2,d1
- move.l d1,(a5)+
-
- add.w #16,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_14CbitM:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- move.l p_CalibrationTable(a6),a3
- moveq #0,d3
- .loop
-
- IFGE __CPU-68020
- move.w (a1)+,d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1)+,d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w (a1)+,d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1)+,d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w (a1)+,d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1)+,d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w (a1)+,d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1)+,d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a5)+
- move.l d2,(a0)+
-
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_14CbitMH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- move.l p_CalibrationTable(a6),a3
- moveq #0,d3
- .loop
-
- IFGE __CPU-68020
- move.w (a1),d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1),d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w 4(a1),d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 4(a1),d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w 8(a1),d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 8(a1),d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w 12(a1),d3
- move.w (a3,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 12(a1),d3
- add.w d3,d3
- move.w (a3,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a5)+
- add.w #16,a1
- move.l d2,(a0)+
-
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
-
- *******************************************************************************
-
- SoftInt_14bitS:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- move.l d4,a4 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- .loop
-
- ; Left High
- move.b (a1),d1
- lsl.l #8,d1
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- move.l d1,(a3)+
-
- ; Left Low
- move.b 1(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 5(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 9(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 13(a1),d1
- lsr.b #2,d1
- move.l d1,(a4)+
-
- ; Right High
- move.b 2(a1),d1
- lsl.l #8,d1
- move.b 6(a1),d1
- lsl.l #8,d1
- move.b 10(a1),d1
- lsl.l #8,d1
- move.b 14(a1),d1
- move.l d1,(a0)+
-
- ; Right Low
- move.b 3(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 7(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 11(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 15(a1),d1
- lsr.b #2,d1
- move.l d1,(a5)+
-
- add.w #16,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
- move.l a4,d4 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
- *******************************************************************************
-
- SoftInt_14bitSH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- move.l d4,a4 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- .loop
-
- ; Left High
- move.b (a1),d1
- lsl.l #8,d1
- move.b 8(a1),d1
- lsl.l #8,d1
- move.b 16(a1),d1
- lsl.l #8,d1
- move.b 24(a1),d1
- move.l d1,(a3)+
-
- ; Left Low
- move.b 1(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 9(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 17(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 25(a1),d1
- lsr.b #2,d1
- move.l d1,(a4)+
-
- ; Right High
- move.b 4(a1),d1
- lsl.l #8,d1
- move.b 12(a1),d1
- lsl.l #8,d1
- move.b 20(a1),d1
- lsl.l #8,d1
- move.b 28(a1),d1
- move.l d1,(a0)+
-
- ; Right Low
- move.b 5(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 13(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 21(a1),d1
- lsr.b #2,d1
- lsl.l #8,d1
- move.b 29(a1),d1
- lsr.b #2,d1
- move.l d1,(a5)+
-
- add.w #32,a1
- dbf d0,.loop
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
- move.l a4,d4 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
-
- *******************************************************************************
-
- SoftInt_14CbitS:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- move.l d4,a4 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- push a6
- move.l p_CalibrationTable(a6),a6
- moveq #0,d3
- .loop
-
- ; Left
- IFGE __CPU-68020
- move.w (a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w 4(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 4(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w 8(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 8(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w 12(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 12(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a4)+
- move.l d2,(a3)+
-
- ; Right
- IFGE __CPU-68020
- move.w 2(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 2(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w 6(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 6(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w 10(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 10(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w 14(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 14(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a5)+
- add.w #16,a1
- move.l d2,(a0)+
-
- dbf d0,.loop
- pop a6
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
- move.l a4,d4 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
-
-
- *******************************************************************************
-
- SoftInt_14CbitSH:
- CONVERT_PRE
-
- move.l d2,a0 ;get buffer ptr
- move.l d3,a3 ;get buffer ptr
- move.l d4,a4 ;get buffer ptr
- move.l d5,a5 ;get buffer ptr
- push a6
- move.l p_CalibrationTable(a6),a6
- moveq #0,d3
- .loop
-
- ; Left
- IFGE __CPU-68020
- move.w (a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w (a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w 8(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 8(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w 16(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 16(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w 24(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 24(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a4)+
- move.l d2,(a3)+
-
- ; Right
- IFGE __CPU-68020
- move.w 4(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 4(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxxxAAxx
- move.w d3,d2
- lsl.l #8,d2 ;xxaaxxxx
- IFGE __CPU-68020
- move.w 12(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 12(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;xxAABBxx
- move.w d3,d2
- lsl.l #8,d2 ;aabbxxxx
- IFGE __CPU-68020
- move.w 20(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 20(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1
- lsl.l #8,d1 ;AABBCCxx
- move.w d3,d2 ;aabbccxx
-
- IFGE __CPU-68020
- move.w 28(a1),d3
- move.w (a6,d3.l*2),d3
- ELSE
- moveq #0,d3
- move.w 28(a1),d3
- add.w d3,d3
- move.w (a6,d3.l),d3
- ENDC
- move.b d3,d1 ;AABBCCDD
- lsr.w #8,d3
- move.b d3,d2 ;aabbccdd
-
- move.l d1,(a5)+
- add.w #32,a1
- move.l d2,(a0)+
-
- dbf d0,.loop
- pop a6
- move.l a0,d2 ;save buffer ptr
- move.l a3,d3 ;save buffer ptr
- move.l a4,d4 ;save buffer ptr
- move.l a5,d5 ;save buffer ptr
-
- CONVERT_POST
-
- lsr.l #1,d0
- move.w d0,AUD0LEN(a0)
- move.w d0,AUD1LEN(a0)
- move.w d0,AUD2LEN(a0)
- move.w d0,AUD3LEN(a0)
- move.w #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
- rts
- EndCode:
-